#ifndef RTP_H
#define RTP_H

#include <stdint.h>
#include <sys/types.h>
#include <sys/socket.h>

#define RTP_START 0
#define RTP_END 1
#define RTP_DATA 2
#define RTP_ACK 3

#define BUFFER_SIZE 2048
#define PKT_SIZE 1461
#define MAX_WINDOWS 32

typedef struct __attribute__((__packed__)) RTP_header
{
    uint8_t type;    // 0: START; 1: END; 2: DATA; 3: ACK
    uint16_t length; // Length of data; 0 for ACK, START and END packets
    uint32_t seq_num;
    uint32_t checksum; // 32-bit CRC
} rtp_header_t;

typedef struct RTP_control_block
{
    uint32_t window_size;
    // TODO: you can add your RTP-related fields here
    struct sockaddr_in sender_addr;   // only for receiver
    struct sockaddr_in receiver_addr; // only for sender
    socklen_t addr_len;
    int seq; // only for sender
    int waitseq;
    char window[MAX_WINDOWS][PKT_SIZE]; // (only for receiver) payload of each window
    int wlen[MAX_WINDOWS];              // (only for receiver)
} rcb_t;

static rcb_t *rcb = NULL;

// different from the POSIX
int rtp_socket(uint32_t window_size, struct sockaddr_in *receiver_addr);

int rtp_listen(int sockfd, int backlog);

int rtp_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

int rtp_bind(int sockfd, struct sockaddr *addr, socklen_t addrlen);

int rtp_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

int rtp_close_receiver(int sockfd);

int rtp_close_sender(int sockfd);

int rtp_sendto(int sockfd, const void *msg, int len, int flags, const struct sockaddr *to, socklen_t tolen);

int rtp_recvfrom(int sockfd, void *buf, int len, int flags, struct sockaddr *from, socklen_t *fromlen);

int rtp_sendto_opt(int sockfd, const void *msg, int len, int flags, const struct sockaddr *to, socklen_t tolen);

int rtp_recvfrom_opt(int sockfd, void *buf, int len, int flags, struct sockaddr *from, socklen_t *fromlen);

#endif // RTP_H
